#pragma once 

#include "socket.hpp"
#include <poll.h>

#define BACK_LOG 5
#define DFT_PORT 8889
#define POLL_CAP 1024
#define DFT_FD   -1

class PollServer{
public:
  ~PollServer() { if (listen_sock > 0) close(listen_sock); }
  static PollServer* GetInstance(int port = DFT_PORT);
  void InitPollServer(); 
  void Run();
private:
  PollServer(int _port) : listen_sock(-1), port(_port){}
  void ClearPollfds(struct pollfd fds[], int num, int default_fd);
  bool SetPollfds(struct pollfd fds[], int num, int fd);
  void HandlerEvent(struct pollfd fds[], int num);
  void UnSetPoolfds(struct pollfd fds[], int index);
private:
  int listen_sock;
  int port;
  static PollServer* instance;
};
PollServer* PollServer::instance = nullptr;

PollServer* PollServer::GetInstance(int port) {
  if (instance == nullptr) 
    instance = new PollServer(port);
  return instance;
}

void PollServer::InitPollServer() {
  listen_sock = Socket::SocketCreate();
  Socket::SocketBind(listen_sock, port);
  Socket::SocketListen(listen_sock, BACK_LOG);
}

void PollServer::ClearPollfds(struct pollfd fds[], int num, int default_fd) {
  for (int i = 0; i < num; i++) {
    fds[i].fd = default_fd;
    fds[i].events = 0;
    fds[i].revents = 0;
  }
}

bool PollServer::SetPollfds(struct pollfd fds[], int num, int fd) {
  for (int i = 0; i < num; i++) {
    if (fds[i].fd == DFT_FD) {
      fds[i].fd = fd;
      fds[i].events |= POLLIN; // 添加读事件
      return true;
    }
  }
  return false;
}



void PollServer::Run() {
  struct pollfd fds[POLL_CAP];
  ClearPollfds(fds, POLL_CAP, DFT_FD);
  SetPollfds(fds, POLL_CAP, listen_sock);
  for (; ;) {
    switch(poll(fds, POLL_CAP, -1)) {
      case 0:
        std::cout << "timeout..." << std::endl; break;
      case -1:
        std::cerr << "poll error" << std::endl;
      default:
        HandlerEvent(fds, POLL_CAP);
        break;
    }
  }
}

void PollServer::UnSetPoolfds(struct pollfd fds[], int index) {
  fds[index].fd = DFT_FD;
  fds[index].events = 0;
  fds[index].revents = 0;
}


void PollServer::HandlerEvent(struct pollfd fds[], int num) {
  for (int i = 0; i < num; i++) {
    if (fds[i].fd == DFT_FD) continue;
    if (fds[i].fd == listen_sock && fds[i].revents & POLLIN) { // 读连接
      struct sockaddr_in peer;
      socklen_t len = sizeof(peer);
      memset(&peer, 0, sizeof(peer));
      int sock = accept(listen_sock, (struct sockaddr*)&peer, &len);
      if (sock < 0) {
        std::cerr << "aceept error" << std::endl;
        continue;
      }
      std::string peer_ip = inet_ntoa(peer.sin_addr);
      short peer_port = ntohs(peer.sin_port);
      std::cout << "get a new link -> [" << peer_ip << ":" << peer_port << "]" << std::endl;
      if (!SetPollfds(fds, POLL_CAP, sock)){
        close(sock);
        std::cout << "poll server is full, close fd :" << sock << std::endl;
      }
    } else if (fds[i].revents & POLLIN) {
#define BUFFER_SIZE 1024
      char buffer [BUFFER_SIZE];
      ssize_t size = read(fds[i].fd, buffer, sizeof(buffer));
      if (size > 0) {
        buffer[size - 1] = 0;
        std::cout << "echo #" <<  buffer << std::endl;
      } else if (size == 0) {
        std::cout << "client quit..." << std::endl;
        close(fds[i].fd);
        UnSetPoolfds(fds, i);
      } else {
        std::cerr << "read error" << std::endl;
        close(fds[i].fd);
        UnSetPoolfds(fds, i);
      }
    }
  }
}























